<body></body>
<script>
  const data = {
    ok: true,
    text: 'hello world'
  }
  let activeEffect
  const bucket = new WeakMap()

  function effect(fn) {
    const effectFn = () => {
      cleanup(effectFn)
      activeEffect = effectFn // effectFn执行会将activeEffect赋值成 当前激活的副作用函数
      fn()
    }
    effectFn.deps = [] // activeEffect.deps用来存储所有与该副作用函数相关联的依赖集合
    effectFn()
  }

  const obj = new Proxy(data, {
    get(target, key) {
      track(target, key) // 把激活的effects添加到桶
      return target[key]
    },
    set(target, key, newVal) {
      target[key] = newVal // effects从桶里取出并执行
      trigger(target, key)
    }
  })

  function cleanup(effectFn) {
    for (let i = 0; i < effectFn.deps.length; i++) {
      const deps = effectFn.deps[i]
      deps.delete(effectFn) // 从依赖集合中 移除 effectFn
    }
    effectFn.deps.length = 0
  }

  // track 函数
  function track(target, key) {
    if (!activeEffect) return target[key]
    let depsMap = bucket.get(target)
    if (!depsMap) {
      bucket.set(target, (depsMap = new Map()))
    }
    let deps = depsMap.get(key)
    if (!deps) {
      depsMap.set(key, (deps = new Set()))
    }
    deps.add(activeEffect) // 将副作用函数加进去
    // deps就是当前副作用函数存在联系的依赖集合
    // 将其添加到activeEffect.deps数组中
    activeEffect.deps.push(deps)
  }

  //  trigger 函数
  function trigger(target, key) {
    const depsMap = bucket.get(target) // target Map
    if (!depsMap) retur
    const effects = depsMap.get(key) // effectFn Set
    const effectsToRun = new Set(effects)
    effectsToRun && effectsToRun.forEach(effectFn => effectFn())
  }

  effect(() => {
    console.log('依赖触发obj.ok:')
    document.body.innerText = obj.ok ? obj.text : 'not'
  })

  setTimeout(() => (obj.ok = false), 500)
  setTimeout(() => (obj.text = 1), 1000)
  setTimeout(() => (obj.text = 2), 1500)
  setTimeout(() => (obj.ok = true), 2000)
  setTimeout(() => (obj.text = 3), 2500)
</script>
